home *** CD-ROM | disk | FTP | other *** search
- /* $Header: archimedes.c,v 3.0.1.1 90/03/27 16:10:41 lwall Locked $
- *
- * (C) Copyright 1989, 1990 Paul Moore.
- *
- * You may distribute under the terms of the GNU General Public License
- * as specified in the README file that comes with the perl 3.0 kit.
- *
- * $Log: archimedes.c,v $
- * Revision 3.0.1.1 90/03/27 16:10:41 lwall
- * patch16: MSDOS support
- *
- * Revision 1.1 90/03/18 20:32:01 dds
- * Initial revision
- *
- */
-
- /*
- * Various Unix compatibility functions for Archimedes RISC OS.
- * This file is basically the same as Paul Moore's one for the original RISC OS
- * port of Perl 3. Some changes have been made to bring it up to date with Perl 5's
- * way of doing things. There are also some extra functions LT - June 1995
- */
-
- #include <limits.h>
- #include <time.h>
- #include "kernel.h"
- #include "swis.h"
-
- #include "EXTERN.h"
- #include "perl.h"
-
- #undef fopen /* fopen was redefined to my_fopen in perl.h but we don't want that here */
-
- /* I'm not sure what the equivalents of these are in Perl 5 so I've just redefined
- them here for the moment. Possibly the Error[1] array in perl.h is the same as err_no */
-
- char err_mess[255]; /* Last OS error string */
- int err_no; /* Last OS error number - just use errno ? */
-
- int h_errno = 0;
-
- /*
- * Save the last OS error return value
- */
- void
- save_err (void)
- {
- _kernel_oserror *err = _kernel_last_oserror();
-
- if (err)
- {
- err_no = err->errnum;
- strcpy(err_mess, err->errmess);
- }
- else
- {
- err_no = 0;
- strcpy(err_mess, "");
- }
- }
-
- /*
- * Sleep function.
- */
- void
- sleep(unsigned len)
- {
- time_t end;
-
- end = time((time_t *)0) + len;
- while (time((time_t *)0) < end)
- ;
- }
-
- /*
- * Make and remove directories
- */
- int
- mkdir(char *dir)
- {
- int retval = 0;
- int type;
- _kernel_osfile_block blk;
-
- if ((type = _kernel_osfile(17,dir,&blk)) != 0)
- {
- err_no = 215;
- sprintf(err_mess, "%s '%s' already exists",
- type == 1 ? "File" : "Directory", dir);
- retval = -1;
- }
-
- blk.start = 0;
- if (_kernel_osfile(8,dir,&blk) == _kernel_ERROR)
- {
- retval = -1;
- save_err();
- }
-
- return retval;
- }
-
- int
- rmdir(char *dir)
- {
- int retval = 0;
- int type;
- _kernel_osfile_block blk;
-
- /* Check that it's a directory */
- if ((type = _kernel_osfile(17,dir,&blk)) != 2)
- {
- blk.load = type;
- _kernel_osfile(19,dir,&blk);
- retval = -1;
- }
- else if (_kernel_osfile(6,dir,&blk) == _kernel_ERROR)
- {
- retval = -1;
- }
-
- if (retval == -1)
- save_err();
-
- return retval;
- }
-
- int
- unlink(char *file)
- {
- int retval = 0;
- _kernel_osfile_block blk;
-
- if (_kernel_osfile(6,file,&blk) == _kernel_ERROR)
- {
- save_err();
- retval = -1;
- }
-
- return retval;
- }
-
- /*
- * Set the timestamp for a file
- */
- void
- stamp (char *file)
- {
- _kernel_osfile_block blk;
-
- _kernel_osfile(9,file,&blk);
- }
-
- /*
- * Set environment variables
- */
- void
- my_setenv(char *var, char *val)
- {
- if (val)
- _kernel_setenv(var,val);
- else
- {
- _kernel_swi_regs regs;
-
- regs.r[0] = (int)var;
- regs.r[1] = 0;
- regs.r[2] = -1;
- regs.r[3] = 0;
- regs.r[4] = 0;
-
- _kernel_swi(OS_SetVarVal,®s,®s);
- }
- }
-
- /*
- * The following code is based on the do_exec and do_aexec functions
- * in file doio.c
- */
- int
- do_aspawn(SV *really,SV **mark, SV **sp)
- {
- return exec_cmdv(0, sp);
- }
-
- int
- do_spawn(char *cmd)
- {
- register SV *str;
- register int status;
-
- _kernel_setenv("Sys$ReturnCode","0");
-
- if (*cmd == '\0')
- return 0;
-
- /* str = newSVpv("Call:",5);
- sv_catpv(str,cmd); */
- status = system(cmd);
- /* sv_free(str); */
-
- if (status == _kernel_ERROR)
- save_err();
-
- return status;
- }
-
- /*
- * Generic exec- or spawn-type command execution.
- */
- int
- exec_cmdv(int chain,SV *arglast)
- {
- register SV **st = AvARRAY(stack);
- register int sp = SvIV(&arglast[1]);
- register int items = SvIV(&arglast[2]) - sp;
- register char *a;
- register char *arg;
- SV *tmps;
- int quotes;
- int status = 0;
- STRLEN len;
-
- if (items) {
- st += ++sp;
-
- /* First, insert "Call:" */
- tmps = newSVpv("Call:", 5);
-
- /* Now add the command name */
- sv_catsv(tmps,*st);
-
- /* Now add each argument in turn */
- for (--items, ++st; items > 0; --items, ++st) {
- if (!*st)
- continue;
-
- /* Separate with spaces */
- sv_catpvn(tmps, " ", 1);
-
- arg = SvPV(*st,len);
-
- /* Do we need to quote this arg? */
- quotes = (strchr(arg,'"') || strchr(arg,' ') || strchr(arg,'\t'));
-
- if (!quotes)
- sv_catsv(tmps, *st);
- else {
- sv_catpvn(tmps, "\"", 1);
-
- /* Add the argument string, backslashing " and \ */
- while ((a = strpbrk(arg,"\"\\")) != Nullch) {
- sv_catpvn(tmps, arg, a - arg);
- sv_catpvn(tmps, "\\", 1);
- sv_catpvn(tmps, a, 1);
- arg = a + 1;
- }
-
- sv_catpv(tmps, arg);
- sv_catpvn(tmps, "\"", 1);
- }
- }
-
- _kernel_setenv("Sys$ReturnCode","0");
- status = system(SvPV(tmps,len));
-
- sv_free(tmps);
-
- if (status == _kernel_ERROR)
- save_err();
- else if (chain)
- exit(0);
- }
-
- return status;
- }
-
- /*
- * Execute a new command, based on an argv array
- */
- void
- execv(cmd,argv)
- char *cmd;
- char **argv;
- {
- register char *a;
- register char *arg;
- SV *tmps;
- STRLEN len;
- int quotes;
- int result;
-
- /* First, insert "Call:" */
- tmps = newSVpv("Call:", 5);
-
- /* Now add the command name */
- sv_catpv(tmps, cmd);
-
- /* Now add each argument in turn */
- for (++argv; *argv; ++argv)
- {
- if (!**argv)
- continue;
-
- /* Separate with spaces */
- sv_catpvn(tmps, " ", 1);
-
- arg = *argv;
-
- /* Do we need to quote this arg? */
- quotes = (strchr(arg,'"') || strchr(arg,' ') || strchr(arg,'\t'));
-
- if (!quotes)
- sv_catpv(tmps, arg);
- else {
- sv_catpvn(tmps, "\"", 1);
-
- /* Add the argument string, backslashing " and \ */
- while ((a = strpbrk(arg,"\"\\")) != Nullch) {
- sv_catpvn(tmps, arg, a - arg);
- sv_catpvn(tmps, "\\", 1);
- sv_catpvn(tmps, a, 1);
- arg = a + 1;
- }
-
- sv_catpv(tmps, arg);
- sv_catpvn(tmps, "\"", 1);
- }
- }
-
- _kernel_setenv("Sys$ReturnCode","0");
-
- result = system(SvPV(tmps,len));
- sv_free(tmps);
-
- if (result != _kernel_ERROR)
- exit(0);
- else
- save_err();
- }
-
- #define SECS1970 2208988800.0 /* Number of seconds from 1/1/1900 to 1/1/1970 */
-
- /* Needs fixed */
- int fstat(int fd, struct stat *buf)
- {
- buf->st_type = 0;
- buf->st_load = 0;
- buf->st_exec = 0;
- buf->st_length = 0;
- buf->st_attr = 0;
- buf->st_ftype = -1;
- buf->st_time = 0.0;
- buf->st_utime = 0;
-
- }
- /*
- * Get a file's catalogue information
- */
- int
- stat(char *file, struct stat *buf)
- {
- int res;
- _kernel_osfile_block blk;
-
- res = _kernel_osfile(5,file,&blk);
-
- if (res == _kernel_ERROR || res == 0)
- return -1;
-
- buf->st_type = res;
- buf->st_load = blk.load;
- buf->st_exec = blk.exec;
- buf->st_length = blk.start;
- buf->st_attr = blk.end;
-
- if ((blk.load & 0xFFF00000) != 0xFFF00000)
- {
- buf->st_ftype = -1;
- buf->st_time = 0.0;
- buf->st_utime = 0;
- }
- else
- {
- double n;
- buf->st_ftype = ((blk.load >> 8) & 0xFFF);
- n = (double)((unsigned)(blk.load & 0xFF));
- n *= 4294967296.0; /* 2^32 */
- n += (double)((unsigned)blk.exec);
- buf->st_time = n;
- n /= 100.0;
- n -= SECS1970;
-
- if (n < 0.0)
- {
- n = 0.0;
- if (dowarn)
- warn("Timestamp too small in stat (%s): set to %d\n",
- file, n);
- }
- else if (n > (double)UINT_MAX)
- {
- n = (double)UINT_MAX;
- if (dowarn)
- warn("Timestamp too large in stat (%s): set to %d\n",
- file, n);
- }
-
- buf->st_utime = (time_t)n;
- }
-
- return 0;
- }
-
- /*
- * Scan through the OS variables selected by a pattern
- */
- char *
- getenvar (char *pat, char **val)
- {
- static char buffer[255];
- static char *pattern;
- static char *name_ptr;
- _kernel_swi_regs regs;
-
- if (pat)
- {
- pattern = pat;
- name_ptr = 0;
- }
-
- regs.r[0] = (int)pattern;
- regs.r[1] = (int)buffer;
- regs.r[2] = 255;
- regs.r[3] = (int)name_ptr;
- regs.r[4] = 3;
-
- if (_kernel_swi(OS_ReadVarVal,®s,®s))
- return 0;
-
- name_ptr = (char *)regs.r[3];
- buffer[regs.r[2]] = '\0';
-
- *val = buffer;
- return name_ptr;
- }
-
-
- /*
- * Get the program start time (as a double)
- */
- void os_starttime (double *dp)
- {
- int i;
- double tmp;
- unsigned char *time;
-
- _kernel_swi_regs regs;
- _kernel_oserror *err = _kernel_swi(OS_GetEnv, ®s, ®s);
-
- if (err)
- {
- err_no = err->errnum;
- strcpy(err_mess, err->errmess);
- *dp = 0.0;
- return;
- }
-
- time = (unsigned char *) regs.r[2];
- tmp = 0.0;
-
- for (i = 4; i >= 0; --i)
- {
- tmp *= 256.0;
- tmp += (double)(time[i]);
- }
-
- *dp = tmp;
- }
-
- /* Rename a file. If a simple OS rename fails, the file is copied.
- * This allows renames across filing system boundaries.
- * If the destination filename exists, the function deletes it (even
- * if locked) first.
- * This function does its best to be totally paranoid about errors, and
- * returns failure if the rename does not work.
- * Returns 0 on success, 1 on failure.
- */
- int frename(const char *old, const char *new)
- {
- register int result;
- register int n;
- FILE *in, *out;
- _kernel_osfile_block blk;
- char buf[BUFSIZ];
-
- /* Check the new file. If it exists, and is not a directory,
- * unlock it (if necessary) and delete it.
- */
- result = _kernel_osfile (17, new, &blk);
-
- /* If the file is a directory, or an error occurred, return failure */
- if (result == 2 || result == _kernel_ERROR)
- return 1;
-
- /* If the file exists and is locked, unlock it */
- if (result == 1 && (blk.end & 0x0008) != 0)
- {
- blk.end &= ~0x0008;
- if (_kernel_osfile(4, new, &blk) == _kernel_ERROR)
- return 1;
- }
-
- /* If the file exists, delete it */
- if (result == 1 && _kernel_osfile(6, new, &blk) == _kernel_ERROR)
- return 1;
-
- /* Now try a simple OS rename */
- if (rename(old, new) == 0)
- return 0;
-
- /* No luck. Get the old file attributes (to ensure that it exists,
- * and is not locked, and for later copying to the new file).
- */
- result = _kernel_osfile (17, old, &blk);
-
- /* If the file is not a simple file, or an error occurred,
- * or the file is locked, return failure.
- */
- if (result != 1 || (blk.end & 0x0008) != 0)
- return 1;
-
- /* Now prepare to copy the file */
- if ((in = fopen(old, "rb")) == NULL)
- return 1;
-
- if ((out = fopen(new, "wb")) == NULL)
- {
- fclose(in);
- return 1;
- }
-
- /* Copy the file */
- while (!feof(in))
- {
- n = fread(buf, 1, BUFSIZ, in);
- if (ferror(in) || fwrite(buf, 1, n, out) != n)
- {
- fclose(in);
- fclose(out);
- remove(new);
- return 1;
- }
- }
-
- if (ferror(in) || fclose(in) == EOF || ferror(out) || fclose(out) == EOF)
- {
- remove(new);
- return 1;
- }
-
- /* Now copy the file attributes across, and delete the old
- * file. Don't worry about errors - they're not too serious,
- * and it's too late to do much anyway.
- */
- _kernel_osfile(1, new, &blk);
- _kernel_osfile(6, old, &blk);
-
- return 0;
- }
-
- int fileno(FILE *file)
- {
- return(file->__file);
- }
-
- FILE *fdopen(int fd, char *mode)
- {
- /* What to do here - about sockets etc */
- char filename[40];
- sprintf(filename,"<Wimp$ScrapDir>.fd%d%s\0",fd,mode);
- printf("Opening %s\n via fdopen",filename);
- return(fopen(filename,mode));
- }
-
- int chmod(const char *path, unsigned int mode)
- {
- return(1);
- }
-
- FILE *warn_fopen(char *name,char *mode)
- {
- FILE *file;
- static int test = -1;
-
- file = fopen(name,mode);
- if(test < 0)
- test = (int)getenv("PERLTEST");
- if(test)
- printf("fopen %s %s\n",name,(file ? " ":" -- Failed"));
- return(file);
- }
-
- FILE *my_fopen(char *name, char *mode)
- {
- register FILE *file;
- char myname[64];
- char newname[64];
-
- strcpy(myname,name);
-
- file = warn_fopen(myname,mode);
-
- if(!file)
- {
- if(suffix_swap(myname))
- {
- file = warn_fopen(myname,mode);
- if(!file && mode[0] == 'r')
- {
- /* It is a perl file so try the script directory as a last resort. *
- * This is a quick fix until I work out why it isn't searching automatically */
- strcpy(newname,"<PerlScript$Dir>.");
- if(strlen(myname) < 20)
- strcat(newname,myname);
- file = warn_fopen(newname,"r");
- if(!file) /* One last try - skip the pl.*/
- {
- strcpy(&newname[17],&myname[3]);
- file = warn_fopen(newname,"r");
- }
- }
- }
- }
- return(file);
- }
-
- int suffix_swap(char *name)
- {
- char *sfix;
- char *fname,tmpname[64];
- int len = strlen(name);
-
- sfix = &name[len];
-
- do
- {
- if(--sfix == name)
- return 0;
- }
- while(*sfix != '.');
- sfix++;
-
- len = strlen(sfix);
- /* just do pl and pm suffixes at the moment */
- if(len == 2)
- {
- tolower(sfix[0]);
- tolower(sfix[1]);
- if(sfix[0] == 'p' && (sfix[1] == 'l' || sfix[1] == 'm'))
- {
- fname = sfix - 2;
- while(*fname != '.' && fname-- != name);
- fname++;
- sprintf(tmpname,".%s",fname);
- tmpname[strlen(fname)-len] = '\0';
- strcpy(fname,sfix);
- strcat(fname,tmpname);
- }
- }
- }
-